//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow.ManagementStudioControls.RegistryManagerModule
{
    using System.Windows;
    using Microsoft.Research.ScientificWorkflow.ManagementStudioModels;
    using System.Collections.ObjectModel;
    using Microsoft.Practices.Unity;
    using ManagementStudioServices.Interfaces;
    using Microsoft.Research.ScientificWorkflow.TridentUtilities;
    using System.Linq;
    using Microsoft.Research.eResearch.Common.Linq;
    using SR = Microsoft.Research.DataLayer;
    using Microsoft.Research.ScientificWorkflow.UIDesigner.WpfComposite;
    using System.Windows.Data;
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// This is the presenter for the type initializer left pane.
    /// </summary>
    public class TypeInitializerLeftPanePresenter : IRegistryManagerLeftPaneItemPresenter
    {
        #region Private Members

        /// <summary>
        /// The unity container.
        /// </summary>
        private IUnityContainer container;

        /// <summary>
        /// Service for registry access.
        /// </summary>
        private IRegistryManagerService registryManagerService;

        /// <summary>
        /// The base model.
        /// </summary>
        private TypeInitializerModel typeInitBaseModel;

        #endregion Private Members

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="TypeInitializerLeftPanePresenter"/> class.
        /// </summary>
        /// <param name="container">The container.</param>
        /// <param name="leftPane">The left pane.</param>
        /// <param name="service">The service.</param>
        public TypeInitializerLeftPanePresenter(IUnityContainer container, TypeInitializerLeftPane leftPane, IRegistryManagerService service)
        {
            this.container = container;
            this.registryManagerService = service;
            this.LeftPaneItems = new ObservableCollection<TypeInitializerModel>();
            this.LeftPaneView = leftPane;
            leftPane.DataContext = this;

            this.TypeInitializerSelectedCommand = new DelegateCommand<TypeInitializerModel>(this.TypeInitializerSelectedCommandExecute);
        }

        #endregion Constructor

        #region Properties

        /// <summary>
        /// Gets or sets the left pane items.
        /// </summary>
        /// <value>The left pane items.</value>
        public ObservableCollection<TypeInitializerModel> LeftPaneItems { get; set; }
        
        /// <summary>
        /// The command for the type initializer selected operation.
        /// </summary>
        public DelegateCommand<TypeInitializerModel> TypeInitializerSelectedCommand { get; private set; }

        #endregion Properties

        #region IRegistryManagerLeftPaneItemPresenter Members

        /// <summary>
        /// Flag to determine whether the presenter is currently selected.
        /// </summary>
        /// <value></value>
        public bool IsSelected { get; set; }

        /// <summary>
        /// Gets or sets the search view.
        /// </summary>
        /// <value>The search view.</value>
        public UIElement SearchView { get; set; }

        /// <summary>
        /// Gets or sets the left pane view.SaveWorkflowCommand
        /// </summary>
        /// <value>The left pane view.</value>
        public UIElement LeftPaneView { get; set; }

        /// <summary>
        /// Gets or sets the left pane presener.
        /// </summary>
        /// <value>The left pane presener.</value>
        public ILeftPaneControl LeftPanePresenter { get; set; }

        /// <summary>
        /// Initializes this instance.
        /// </summary>
        public void Initialize()
        {
            try
            {
                this.LeftPaneItems.Clear();
                this.BuildList();
            }
            catch (TridentCustomException ex)
            {
                TridentMessageBox.ShowTridentErrorMessageBox(ex.Message);
            }
        }

        /// <summary>
        /// Refreshes this instance.
        /// </summary>
        /// <param name="selectedModel"></param>
        public void Refresh(BaseRegMgrModel selectedModel)
        {
            this.Initialize();
            if (selectedModel != null)
            {
                if (selectedModel is TypeInitializerModel)
                {
                    BaseRegMgrModel modelToSelect = selectedModel.GetModelById(selectedModel, this.LeftPaneItems.Cast<BaseRegMgrModel>());
                    if (modelToSelect != null)
                    {
                        this.TypeInitializerSelectedCommand.Execute(modelToSelect as TypeInitializerModel);
                    }
                }
                else
                {
                    this.OnSelectRoot();
                }
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Builds the list of type initializers.
        /// </summary>
        private void BuildList()
        {
            // Create the empty lightweight type intializer model that will inturn hold the type initializers.
            typeInitBaseModel = new TypeInitializerModel("Type Initializer", string.Empty);
            this.LeftPaneItems.Add(typeInitBaseModel);

            // Get the list of type initializers and add them to the above created model.
            IEnumerable<SR.TypeInitializer> typeInitializers = this.registryManagerService.GetTypeInitializers();
            if (null != typeInitializers)
            {
                typeInitializers.ForEach(typeInitializer => typeInitBaseModel.Children.Add(new TypeInitializerModel(typeInitializer)));
                typeInitBaseModel.Children.ForEach(child => child.Parent = typeInitBaseModel);
            }
        }
        
        /// <summary>
        /// On selection of a type initializer.
        /// </summary>
        /// <param name="model">The model.</param>
        private void TypeInitializerSelectedCommandExecute(TypeInitializerModel model)
        {
            IRegistryManagerCenterPanePresenter centerPanePresenter = RegistryManagerPresenterFactory.FetchCenterPanePresenter(typeof(TypeInitializerModel));
            centerPanePresenter.DeleteCommand = new DelegateCommand<BaseRegMgrModel>(this.OnDelete);
            centerPanePresenter.RefreshCommand = new DelegateCommand<BaseRegMgrModel>(this.Refresh);
            centerPanePresenter.SelectRootCommand = new DelegateCommand<object>(p => this.OnSelectRoot());
            (this.LeftPanePresenter as RegistryManagerLeftPanePresenter).ItemSelected.Execute(new object[] { centerPanePresenter, this, new SaveStateHandler(SaveStatus.Valid) });
            if (model != null && !model.IsSelected)
            {
                model.IsSelected = true;
            }

            centerPanePresenter.SelectedModel = model;
        }

        /// <summary>
        /// Called when the center pane requests a root selection.
        /// </summary>
        private void OnSelectRoot()
        {
            if (this.typeInitBaseModel != null)
            {
                this.typeInitBaseModel.IsSelected = false;
                this.typeInitBaseModel.IsSelected = true;
            }
        }

        /// <summary>
        /// Called on delete request of a type intializer.
        /// </summary>
        /// <param name="model">The model.</param>
        private void OnDelete(BaseRegMgrModel modelToDelete)
        {
            if (modelToDelete != null)
            {
                TypeInitializerModel model = modelToDelete as TypeInitializerModel;
                if (model != null && model.Parent != null)
                {
                    BaseRegMgrModel parentModel = model.Parent.GetModelById(model.Parent, this.LeftPaneItems.Cast<BaseRegMgrModel>());
                    if (parentModel != null && parentModel.Children.Contains(model))
                    {
                        parentModel.Children.Remove(model);
                    }
                }
            }
        }

        #endregion Private Methods
    }
}
